﻿// $Id: NotNullRule.cs 10 2008-02-29 15:58:02Z mcartoixa $

/* ***************************************************************************
 *                                                                           *
 * Copyright © 2007 NourY Solutions                                          *
 *                                                                           *
 * This file is part of DataRules.                                           *
 *                                                                           *
 * DataRules is free software; you can redistribute it and/or modify it      *
 * under the terms of the GNU Lesser General Public License as published     *
 * by the Free Software Foundation; either version 3 of the License, or      *
 * (at your option) any later version.                                       *
 *                                                                           *
 * DataRules is distributed in the hope that it will be useful, but          *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this program.  If not, see                             *
 * <http://www.gnu.org/licenses/lgpl.html>.                                  *
 *                                                                           *
 *************************************************************************** */

/*! \file
 * \brief Definition of \c Salamanca.DataRules.NotNullRule.
 *
 * \author $Author: mcartoixa $
 * \date $Date: 2008-02-29 16:58:02 +0100 (ven., 29 févr. 2008) $
 * \version $Revision: 10 $
 */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;

namespace Salamanca.DataRules
{



    ///////////////////////////////////////////////////////////////////////////
    ///
    /// <summary>Business rule that specifies that a property may not be <c>null</c>.</summary>
    /// <example>
    ///   <code>
    /// using Salamanca.DataRules;
    /// 
    /// public class City
    /// {
    ///     private string _ZipCode;
    /// 
    ///     public string ZipCode
    ///     {
    ///         get
    ///         {
    ///              return _ZipCode;
    ///         }
    ///     }
    /// 
    ///     protected List&lt;IRule&gt; CreateRules()
    ///     {
    ///         List&lt;IRule&gt; ret=new List&lt;IRule&gt;();
    /// 
    ///         ret.Add(
    ///             new NotNullRule&lt;City&gt;(
    ///                 "ZipCode"
    ///             )
    ///         );
    /// 
    ///         return ret;
    ///     }
    /// }
    ///   </code>
    /// </example>
    ///
    ///////////////////////////////////////////////////////////////////////////

    public class NotNullRule<T>:
        GenericRule<T>
    {

        /// <summary>Constructor.</summary>
        /// <param name="propertyName">The name of the property. This cannot be an empty string (<c>""</c>).</param>
        /// <exception cref="ArgumentException">
        ///   <para>The property <paramref name="propertyName" /> cannot be found on the specified <typeparamref name="T">type</typeparamref>.</para>
        ///   <para>The property <paramref name="propertyName" /> is not readable.</para>
        ///   <para>The property <paramref name="propertyName" /> is an indexer.</para>
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///   <para><paramref name="propertyName" /> is <c>null</c>.</para>
        /// </exception>
        public NotNullRule(string propertyName):
            this(propertyName, string.Format(CultureInfo.CurrentCulture, Resources.SR.NotNullRuleDescription, propertyName))
        {
        }

        /// <summary>Constructor.</summary>
        /// <param name="propertyName">The name of the property. This cannot be an empty string (<c>""</c>).</param>
        /// <param name="description">The description of the rule.</param>
        /// <exception cref="ArgumentException">
        ///   <para>The property <paramref name="propertyName" /> cannot be found on the specified <typeparamref name="T">type</typeparamref>.</para>
        ///   <para>The property <paramref name="propertyName" /> is not readable.</para>
        ///   <para>The property <paramref name="propertyName" /> is an indexer.</para>
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///   <para><paramref name="propertyName" /> is <c>null</c>.</para>
        ///   <para><paramref name="description" /> is <c>null</c>.</para>
        /// </exception>
        public NotNullRule(string propertyName, string description):
            base(propertyName, description)
        {
        }

        /// <summary>Validates the rule on the specified target.</summary>
        /// <remarks>
        ///   <para>The <see cref="GenericRule{T}.Property" /> value is checked for <c>null</c>ity.</para>
        /// </remarks>
        /// <param name="target">The instance against which the rule is validated.</param>
        /// <returns><c>true</c> if the instance is valid for the rule, <c>false</c> if not.</returns>
        protected override bool DoValidate(object target)
        {
            return (Property.GetValue(target, null)!=null);
        }
    }



    ///////////////////////////////////////////////////////////////////////////
    ///
    /// <summary>Business rule attribute that specifies that a property may not be <c>null</c>.</summary>
    /// <example>
    ///   <code>
    /// using Salamanca.DataRules;
    /// 
    /// public class City
    /// {
    ///     private string _ZipCode;
    /// 
    ///     [NotNullRule]
    ///     public string ZipCode
    ///     {
    ///         get
    ///         {
    ///              return _ZipCode;
    ///         }
    ///     }
    /// 
    ///     protected List&lt;IRule&gt; CreateRules()
    ///     {
    ///         return Rules.CreateAttributedRule(GetType());
    ///     }
    /// }
    ///   </code>
    /// </example>
    ///
    ///////////////////////////////////////////////////////////////////////////

    [AttributeUsage(AttributeTargets.Property, Inherited=true, AllowMultiple=false)]
    public sealed class NotNullRuleAttribute:
        RuleAttribute
    {

        /// <summary>Constructor.</summary>
        public NotNullRuleAttribute():
            base(typeof(NotNullRule<>))
        {
        }

        /// <summary>Gets the rule associated with the attribute.</summary>
        public override IRule GetRule(Type targetType, string propertyName)
        {
            if (string.IsNullOrEmpty(Description))
                return (IRule)typeof(NotNullRule<>)
                    .MakeGenericType(targetType)
                    .GetConstructor(new Type[] { typeof(string) })
                    .Invoke(new object[] { propertyName });
            else
                return (IRule)typeof(NotNullRule<>)
                    .MakeGenericType(targetType)
                    .GetConstructor(new Type[] { typeof(string), typeof(string) })
                    .Invoke(new object[] { propertyName, Description });
        }

    }

}
